/**
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 */
package com.ouheng.common.utils;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;

import javax.servlet.ServletRequest;

import org.springframework.util.Assert;

/**
 * Http与Servlet工具类.
 */
public class ServletsUtils {
	
	/**
	 * 取得带相同前缀的Request Parameters, copy from spring WebUtils.
	 * 
	 * 返回的结果的Parameter名已去除前缀.
	 */
	public static Map<String, Object> getParametersStartingWith(ServletRequest request, String prefix) {
		Assert.notNull(request, "Request must not be null");
		Enumeration<?> paramNames = request.getParameterNames();
		Map<String, Object> params = new TreeMap<>();
		if (prefix == null) {
			prefix = "";
		}
		int rowLength = 0;
		while (paramNames != null && paramNames.hasMoreElements()) {
			String paramName = (String) paramNames.nextElement();
			if ("".equals(prefix) || paramName.startsWith(prefix)) {
				String unprefixed = paramName.substring(prefix.length());
				String[] values = request.getParameterValues(paramName);
				for (String string : values) {
						//对获取的值进行转码
						string = StringUtils.getUTF8(string);
				}
				if (values == null || values.length == 0) {
					// Do nothing, no values found at all.
				} else if (values.length > 0) {
				    rowLength = values.length;
					params.put(unprefixed, values);
				} else {
					//baiyang 当传参的值为空字符串，则不放入MAP
//					if(!"".equals(values[0])){
//						params.put(unprefixed, values[0].trim());
//					}
				}
			}
		}
		//设置分路数据长度
		params.put("rowLength", rowLength);
		return params;
	}

	 /** 
     * 将一个 Map 对象转化为 JavaBean 
     * @param type 要转化的类型 
     * @param map 包含属性值的 map 
     * @return 转化出来的 JavaBean 对象 
     * @throws IntrospectionException 
     *             如果分析类属性失败 
     * @throws IllegalAccessException 
     *             如果实例化 JavaBean 失败 
     * @throws InstantiationException 
     *             如果实例化 JavaBean 失败 
     * @throws InvocationTargetException 
     *             如果调用属性的 setter 方法失败 
	 * @throws ParseException 
	 * @throws IllegalArgumentException 
     */ 
    public static List<Object> convertObjectList(Class type, ServletRequest request, String prefix) 
            throws IntrospectionException, IllegalAccessException, 
            InstantiationException, InvocationTargetException, IllegalArgumentException, ParseException {
        List<Object> objectList = new ArrayList<Object>();
        //获取分路信息map
        Map<String, Object> params =getParametersStartingWith(request,prefix);
        //map的value数组对应的索引
        int rowLength = (Integer)params.get("rowLength");
        for (int mapValueIndex = 0; mapValueIndex< rowLength; mapValueIndex++) { 
            // 获取类属性
            BeanInfo beanInfo = Introspector.getBeanInfo(type); 
            // 创建 JavaBean 对象 
            Object obj = type.newInstance(); 
            // 给 JavaBean 对象的属性赋值 
            PropertyDescriptor[] propertyDescriptors =  beanInfo.getPropertyDescriptors();
            for (int i = 0; i< propertyDescriptors.length; i++) { 
                PropertyDescriptor descriptor = propertyDescriptors[i]; 
                String propertyName = descriptor.getName();
                if (params.containsKey(propertyName)) {
                    String[] values = (String[])params.get(propertyName);
                    // 下面一句可以 try 起来，这样当一个属性赋值失败的时候就不会影响其他属性赋值。 
                    String value = values[mapValueIndex]; 
                    Method method = descriptor.getWriteMethod();
                    Class<?>[] clazz = method.getParameterTypes();  
                    String parameterType = clazz[0].getName(); 
                    if(StringUtils.isNotEmpty(value)){
                        if(parameterType.equals("java.lang.String")){  
                            method.invoke(obj,value);  
                        }  
                        else if(parameterType.equals("java.lang.Integer")){  
                            method.invoke(obj, new Integer(value));  
                        }
                        else if(parameterType.equals("java.math.BigDecimal")){  
                            method.invoke(obj, new BigDecimal(value));  
                        }
                        else if(parameterType.equals("java.util.Date")){
                            method.invoke(obj,DateUtils.parseDate(value));  
                        }
                    }
                }
            }
            objectList.add(obj);
        }
        return objectList; 
    } 

    /** 
     * 将一个 JavaBean 对象转化为一个  Map 
     * @param bean 要转化的JavaBean 对象 
     * @return 转化出来的  Map 对象 
     * @throws IntrospectionException 如果分析类属性失败 
     * @throws IllegalAccessException 如果实例化 JavaBean 失败 
     * @throws InvocationTargetException 如果调用属性的 setter 方法失败 
     */ 
    public static Map convertBean(Object bean) 
            throws IntrospectionException, IllegalAccessException, InvocationTargetException { 
        Class type = bean.getClass(); 
        Map returnMap = new HashMap(); 
        BeanInfo beanInfo = Introspector.getBeanInfo(type); 

        PropertyDescriptor[] propertyDescriptors =  beanInfo.getPropertyDescriptors(); 
        for (int i = 0; i< propertyDescriptors.length; i++) { 
            PropertyDescriptor descriptor = propertyDescriptors[i]; 
            String propertyName = descriptor.getName(); 
            if (!propertyName.equals("class")) { 
                Method readMethod = descriptor.getReadMethod(); 
                Object result = readMethod.invoke(bean, new Object[0]); 
                if (result != null) { 
                    returnMap.put(propertyName, result); 
                } else { 
                    returnMap.put(propertyName, ""); 
                } 
            } 
        } 
        return returnMap; 
    } 
	
	/**
	 * 组合Parameters生成Query String的Parameter部分, 并在paramter name上加上prefix.
	 * 
	 * @see #getParametersStartingWith
	 */
	public static String encodeParameterStringWithPrefix(Map<String, Object> params, String prefix) {
		if (params == null || params.size() == 0) {
			return "";
		}
		if (prefix == null) {
			prefix = "";
		}
		StringBuilder queryStringBuilder = new StringBuilder();
		try {
			Iterator<Entry<String, Object>> it = params.entrySet().iterator();
			while (it.hasNext()) {
				Entry<String, Object> entry = it.next();
				if(entry.getValue()==null){
					continue;
				}
				queryStringBuilder.append(prefix).append(entry.getKey()).append('=').append(java.net.URLEncoder.encode(entry.getValue().toString(),"utf-8"));
				if (it.hasNext()) {
					queryStringBuilder.append('&');
				}
			}
		} catch (UnsupportedEncodingException e) {
		}
		return queryStringBuilder.toString();
	}

}
